﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using TjZheng.Framework;

namespace TjZheng.WeiXin.SDK.Pay
{
    public class WxPayPackage : WeiXinPackage
    {

        /// <summary>
        /// 设置数据表值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void SetValue(string key, object value)
        {
            this[key] = value;
        }

        /// <summary>
        /// 获取数据包值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public object GetValue(string key)
        {
            object obj = null;
            this.TryGetValue(key, out obj);
            return obj;
        }

        /// <summary>
        /// 判断数据包是否已经设值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool IsValueSet(string key)
        {
            object obj = null;
            this.TryGetValue(key, out obj);
            if (null != obj)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 创建签名
        /// </summary>
        /// <returns></returns>
        public virtual string CreateSign(string mkey)
        {
            if (mkey.IsNull())
            {
                throw new ArgumentNullException("mkey");
            }
            //转url格式
            string str = this.ConvertToUrlQueryString();
            //在string后加入API KEY
            str += "&key=" + mkey;
            return WxPayApi.EncodeMD5(str).ToUpper();
        }

        /// <summary>
        /// 检查签名
        /// </summary>
        /// <returns></returns>
        public virtual bool CheckSign(string mkey)
        {
            if (mkey.IsNull())
            {
                throw new ArgumentNullException("mkey");
            }
            //如果没有设置签名，则跳过检测
            if (!this.IsValueSet("sign"))
            {
                throw new WxPayException("WxPayPackage签名不存在!");
            }

            //获取接收到的签名
            string return_sign = Convert.ToString(this.GetValue("sign"));

            if (return_sign.IsNull())
            {
                throw new WxPayException("WxPayPackage签名不存在!");
            }

            //在本地计算新的签名
            string cal_sign = this.CreateSign(mkey);
            if (cal_sign == return_sign)
            {
                return true;
            }
            throw new WxPayException("WxPayPackage签名验证错误!");
        }

        public override string ConvertToUrlQueryString()
        {
            string buff = "";
            foreach (string key in this.Keys)
            {
                if (Convert.ToString(this[key]).IsNull())
                {
                    throw new WxPayException("WxPayPackage内部含有值为null的字段!");
                }

                if (key != "sign")
                {
                    buff += key + "=" + this[key] + "&";
                }
            }
            buff = buff.Trim('&');
            return buff;
        }

        public override string ConvertToXml()
        {
            //数据为空时不能转化为xml格式
            if (this.IsNull())
            {
                throw new WxPayException("WxPayPackage数据为空!");
            }

            StringBuilder objStringBuilder = new StringBuilder("<xml>");
            foreach (string key in this.Keys)
            {
                //字段值不能为null，会影响后续流程
                if (this[key] == null)
                {
                    throw new WxPayException("WxPayPackage内部含有值为null的字段!");
                }

                //除了string和int类型不能含有其他数据类型
                if (this[key].GetType() == typeof(int))
                {
                    objStringBuilder.Append("<" + key + ">" + this[key] + "</" + key + ">");
                    continue;
                }
                if (this[key].GetType() == typeof(string))
                {
                    objStringBuilder.Append("<" + key + ">" + "<![CDATA[" + this[key] + "]]></" + key + ">");
                    continue;
                }
                throw new WxPayException("WxPayPackage字段数据类型错误!");
            }
            objStringBuilder.Append("</xml>");
            return objStringBuilder.ToString();
        }

        public static WxPayPackage ParseFromXml(string xml)
        {
            if (xml.IsNull())
            {
                throw new WeiXinException("将空的xml串转换为WeiXinPackage不合法!");
            }

            XmlDocument objXmlDocument = new XmlDocument();
            objXmlDocument.LoadXml(xml);
            XmlNode objXmlNode = objXmlDocument.FirstChild;//获取到根节点<xml>
            XmlNodeList objXmlNodeList = objXmlNode.ChildNodes;

            WxPayPackage objWxPayPackage = new WxPayPackage();

            foreach (XmlNode objChildNode in objXmlNodeList)
            {
                XmlElement objXmlElement = (XmlElement)objChildNode;
                objWxPayPackage[objXmlElement.Name] = objXmlElement.InnerText;//获取xml的键值对到WxPayPackage内部的数据中
            }

            return objWxPayPackage;
        }

        public static WxPayPackage ParseFromStream(Stream objStream)
        {
            if (objStream == null)
            {
                throw new ArgumentNullException("objStream");
            }
            int count = 0;
            byte[] buffer = new byte[1024];
            StringBuilder objStringBuilder = new StringBuilder();
            while ((count = objStream.Read(buffer, 0, 1024)) > 0)
            {
                objStringBuilder.Append(Encoding.UTF8.GetString(buffer, 0, count));
            }
            objStream.Flush();
            objStream.Close();
            objStream.Dispose();

            return ParseFromXml(objStringBuilder.ToString());
        }
    }
}
